/**
 * 全局Loading管理工具
 */
import { ElLoading } from 'element-plus'
import { computed } from 'vue'

class LoadingManager {
  constructor() {
    this.loadingInstance = null
    this.loadingCount = 0
    this.requestQueue = new Map()
  }

  /**
   * 显示全局loading
   * @param {Object} options 配置选项
   */
  show(options = {}) {
    this.loadingCount++

    if (!this.loadingInstance) {
      this.loadingInstance = ElLoading.service({
        text: '正在加载...',
        background: 'rgba(0, 0, 0, 0.8)',
        ...options
      })
    }
  }

  /**
   * 隐藏全局loading
   * @param {boolean} force 是否强制隐藏
   */
  hide(force = false) {
    if (force) {
      this.loadingCount = 0
    } else {
      this.loadingCount = Math.max(0, this.loadingCount - 1)
    }

    if (this.loadingCount === 0 && this.loadingInstance) {
      this.loadingInstance.close()
      this.loadingInstance = null
    }
  }

  /**
   * 为API请求添加loading
   * @param {string} requestId 请求唯一标识
   * @param {Object} options 配置选项
   */
  addRequest(requestId, options = {}) {
    if (this.requestQueue.has(requestId)) {
      return // 避免重复请求
    }

    this.requestQueue.set(requestId, true)
    this.show(options)
  }

  /**
   * 移除API请求loading
   * @param {string} requestId 请求唯一标识
   */
  removeRequest(requestId) {
    if (this.requestQueue.has(requestId)) {
      this.requestQueue.delete(requestId)
      this.hide()
    }
  }

  /**
   * 清除所有请求
   */
  clearAllRequests() {
    this.requestQueue.clear()
    this.hide(true)
  }

  /**
   * 获取当前loading状态
   */
  get isLoading() {
    return this.loadingCount > 0
  }

  /**
   * 获取当前请求数量
   */
  get requestCount() {
    return this.requestQueue.size
  }
}

// 导出单例
export const loadingManager = new LoadingManager()

/**
 * Loading装饰器 - 用于函数或方法
 * @param {Object} options 配置选项
 * @returns {Function} 装饰器函数
 */
export function withLoading(options = {}) {
  return function (target, propertyKey, descriptor) {
    const originalMethod = descriptor.value

    descriptor.value = async function (...args) {
      const requestId = `${target.constructor.name}.${propertyKey}_${Date.now()}`

      try {
        loadingManager.addRequest(requestId, options)
        return await originalMethod.apply(this, args)
      } finally {
        loadingManager.removeRequest(requestId)
      }
    }

    return descriptor
  }
}

/**
 * Loading工具Hook
 * @param {Object} options 默认配置
 * @returns {Object} loading相关方法
 */
export function useLoading(options = {}) {
  const show = (customOptions = {}) => {
    loadingManager.show({ ...options, ...customOptions })
  }

  const hide = (force = false) => {
    loadingManager.hide(force)
  }

  const withLoadingWrapper = async (promise, customOptions = {}) => {
    const requestId = `useLoading_${Date.now()}_${Math.random()}`

    try {
      loadingManager.addRequest(requestId, { ...options, ...customOptions })
      return await promise
    } finally {
      loadingManager.removeRequest(requestId)
    }
  }

  return {
    show,
    hide,
    withLoading: withLoadingWrapper,
    isLoading: computed(() => loadingManager.isLoading),
    requestCount: computed(() => loadingManager.requestCount)
  }
}

export default loadingManager
